/* test_threads_func_uthread_create():
	A test for uthread_create(). Test the regular case + the error case.

	* Trys to create threads with invalid priority.
	Thread 0 creates thread 1 with prio 1.
	Thread 1 create thread 2 with prio 8.

	We verify that the timeslices given to threads 1 and 2 are ok.
*/


#include <assert.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#include "test_general.h"

#include "user_threads.h"


bool test_threads_func_uthread_create();

#define THREADS_NUM 3

double global_1,global_2;
/* Increamented in threads 1,2 respectivly */


static int thread2_start_routine(void * param);

static int thread1_start_routine(void * param) {
	printf("in start 1 \n");
	global_1 = -1;
	TEST_ASSERT( 53 == (*((int*)param)) );

	TEST_ASSERT (uthread_self() == 1);

	thread_id id = uthread_create(thread2_start_routine, NULL);
	TEST_ASSERT(id == 2);
	printf("2 was created ! \n");

	thread_ok[1] = true;
	while(true) {
		global_1 += 1.0;
	}
}

static int thread2_start_routine(void * param) {
	global_2 = -2;
	TEST_ASSERT( NULL == param );
	TEST_ASSERT (uthread_self() == 2);

	thread_ok[2] = true;
	while(true) {
		global_2 += 1.0;
	}
}

bool test_threads_func_uthread_create()
{
	init_individual_test();

	int tmp;

	if (initilize_uthread_in_each_test) {
		tmp = uthread_init();
		printf("after init \n");
		TEST_ASSERT(tmp == UTHREAD_SUCCESS);
	}


	int FiftyThree = 53;

	/* Checking: UTHREAD_FAIL 

	tmp = uthread_create(thread1_start_routine, &FiftyThree,0);
	TEST_ASSERT(UTHREAD_FAIL == tmp);
	tmp = uthread_create(thread1_start_routine, &FiftyThree,-1);
	TEST_ASSERT(UTHREAD_FAIL == tmp);
	tmp = uthread_create(thread1_start_routine, &FiftyThree,9);
	TEST_ASSERT(UTHREAD_FAIL == tmp); */


	thread_id threads[THREADS_NUM];
	threads[0] = uthread_self();

	global_1 = 0.0;
	global_2 = 0.0;

	threads[1] = uthread_create(thread1_start_routine, &FiftyThree);
	printf("2\n");
	TEST_ASSERT(threads[1] == 1);
time_t now;
time(&now);
printf("time : %s\n", ctime(&now));
	some_long_operation(0.5);

time(&now);
printf("time : %s\n", ctime(&now));
	double ratio = global_2 / global_1;
	printf("global _1 : %d , global_2 : %d \n", global_1, global_2);
	/* We expect ratio to be close to 8   --  we dont have priority so this is not important
	TEST_ASSERT(ratio > 7.0);
	TEST_ASSERT(ratio < 9.0);*/

	tmp = uthread_cancel(threads[1]);
	printf("3\n");
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);
	tmp = uthread_cancel(2);
	printf("4 : tmp = %d == succes = %d \n", tmp, UTHREAD_SUCCESS);
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);

	tmp = uthread_join(threads[1],NULL);
	printf("5\n");
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);
	tmp = uthread_join(2,NULL);
	printf("6\n");
	TEST_ASSERT(UTHREAD_SUCCESS == tmp);


	thread_ok[0] = true;
	printf("7\n");
	TEST_ASSERT(are_all_threads_ok(THREADS_NUM));

	return true;
}
